<?php

declare(strict_types=1);

namespace App\Middleware\Api;

use Hyperf\HttpServer\Contract\RequestInterface;
// use Hyperf\HttpServer\Contract\ResponseInterface as HttpResponse;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Hyperf\Context\Context;
use App\Constants\Status;
use App\Common\RedisCache;
use Psr\Container\ContainerInterface;
use App\Exception\ApiException;
use App\Service\DataResource;

class AppToolsMiddleware implements MiddlewareInterface
{
    /**
     * @var ContainerInterface
     */
    protected $container;

    /**
     * @var RequestInterface
     */
    protected $request;

    public function __construct(ContainerInterface $container, RequestInterface $request)
    {
        $this->container = $container;
        $this->request = $request;
    }

    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
    {
        header("Access-Control-Allow-Origin: *");
        header("Access-Control-Allow-Methods: POST, GET");
        header('Access-Control-Allow-Headers:T-Token,T-Sign');
        $path = $this->request->path();
        if ($path === '/favicon.ico') {
            unset($path);
            throw new ApiException(Status::INVALID_API);
        }
        if ($path === '/') {
            unset($path);
            throw new ApiException(Status::INVALID_API);
        }
        $privateKey = '-----BEGIN PRIVATE KEY-----
MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAMg5qhcIINvsXWGJ
1/yCFM+bKJ+PvRv2bEGX3thqopPyQe5mKHFCJ/Y6cgY1qujWlZ19w1hnDOR0KfC2
YTk44IuMMUwjjahDPi0VQXV0eLe5eDjPqRjTw5oxve9Lp3XEbQQw9LdMoAMNR0GH
jPch7uUOGwYgI1R+IhoIJMlA5QhHAgMBAAECgYEAkujsihWmtnbJVYXkehuf1WwM
9HZs1RWL/NzH35buTwtToO5IAkH+PEZJ35CFJG4+PN5H9Jc3+G/bTgkjcO7woWVa
WTw+zPjq8y8NiT8G3LMRy4U/SW1xOH+wfuftD+TzNBpr4Sw+T0uujWWa8BkItTjr
62Kbsko6QBv3uwY8cyECQQD7ghKuynTE0UopudiSaRUZFI0o2Smr+jPjsHT5nQHR
W2PpawpLgJo0hzIa3U+ReBxWmVRYnkp/5lKUOmGCL+1pAkEAy80epyhIavj8okqy
RWRRJsqOFp5H6Ot+V6FTuzqBpyKSSl7B7R5eWSPCL6RI1TYRDvsr0bmXO9kmEO0E
73yiLwJASQy3lnMRRVUwgDwNbkD9MsKoWVPx6ZSLW7eV0iZLL96mf1ZqsBFTOKyH
3gunn63ONUzllbOsGcfw9kKarbBz+QJAOaBHUZanW3AJ503duJdUBvbxVF3vEWI9
OEQKq/8wF/VDjjna9dRHc0cUKmp2masPCcBltIiYxbhx9gk/AwSnywJAZFJRDhrH
gFxHiTR40mRA2MKt85Ayo7PxR6SWTl6aASoFZOch3K4D+sbDsBOjBfr78h/NGzpl
erEmZKcuV4e15g==
-----END PRIVATE KEY-----';
$data = $this->request->input('data');
// 必须有apkey
        if (empty($data)) {
            throw new ApiException(Status::CODE_FORBIDDEN, 'data is null');
        }
        openssl_private_decrypt(base64_decode($data), $decrypted, $privateKey);
        if (empty($decrypted)) {
            throw new ApiException(Status::CODE_FORBIDDEN, 'encrypt data is null');
        }
        $decrypted = json_decode($decrypted,true);
        if (empty($decrypted)) {
            throw new ApiException(Status::CODE_FORBIDDEN, 'encrypt data is error');
        }
        // 必须有apkey
        if (empty($decrypted['v'])) {
            throw new ApiException(Status::CODE_FORBIDDEN, 'v is null');
        }
        Context::set('data', $decrypted);
        $platform = ($decrypted['platform']) ? $decrypted['platform'] : $decrypted['devi'];
        $platform = (isset($platform) && !empty($platform)) ? strtolower($platform) : 'null';
        switch ($platform) {
            case 'ios':
                $whereIn = ['platform', [2, 3]];
                break;
            case 'android':
            case 'ard':
                $whereIn = ['platform', [1, 3]];
                break;
            default:
                $whereIn = ['platform', [1, 2, 3]];
                break;
        }
        Context::set('platformWhereIn', $whereIn);
        if ($platform == 'smartapp' || $platform == 'xcx') {
            Context::set('smartapp', 1);
        }
        // 必须有apkey
        if (empty($decrypted['_t'])) {
            throw new ApiException(Status::CODE_FORBIDDEN, 't is null');
        }
        if ($decrypted['_t'] > (time() + 300) || $decrypted['_t'] < (time() - 300)) {
            throw new ApiException(Status::CODE_FORBIDDEN, 'Illegal request');
        }
        // $this->checkSecure($appkey);
        //       // 判断apkey的正确性
        //       $this->checkPlatformAppkey($appkey);
        //       unset($appkey);
        //       // 权限策略判断
        //       $this->checkUserRank($path);
        //       unset($path);
        //       $this->getPlatFormSetting();
        return $handler->handle($request);
    }
    /**
     * 常规安全验证
     * @param string $appkey
     * @author QianLong <87498106@qq.com>
     * @version 1.0.0
     */
    public function checkSecure($appkey)
    {
        $bannedValue = redis()->get('openmqt_' . $appkey . '_FENGJIN');
        if ($bannedValue >= 1) {
            throw new ApiException(Status::CODE_FAIL, '用户被禁，如有疑问可咨询：87989431、87498106');
        }
        $dataResource = new DataResource;
        $remoteIp = $dataResource->getClientIp($this->request);
        $refuseValue = redis()->get('openmqt_' . $remoteIp . '_REFUSE');
        if ($refuseValue >= 1) {
            throw new ApiException(Status::CODE_FAIL, '请求超限');
        }
        if (time() > 1581696000) {
            if (!redis()->exists('openmqt_IPWHITE-' . $remoteIp)) {
                throw new ApiException(Status::CODE_FAIL, $remoteIp . ' is illegal ip. See: http://dev.21ds.cn/article/290.html');
            }
        }
    }
    /**
     * appkey真实性验证
     * @param string $appkey
     * @author QianLong <87498106@qq.com>
     * @version 1.0.0
     */
    public function checkPlatformAppkey(string $appkey)
    {
        $redisCacheObj = new RedisCache();
        $getUserSettingData = $redisCacheObj->getUserSettingByAppkey($appkey);
        unset($redisCacheObj);
        if (empty($getUserSettingData)) {
            throw new ApiException(Status::NO_APPKEY);
        }
        $bannedValue = redis()->get('openmqt_FENGJIN:UID:' . $getUserSettingData['uid']);
        if ($bannedValue >= 1) {
            throw new ApiException(Status::CODE_FAIL, '用户被禁，如有疑问可咨询：87989431、87498106');
        }
        Context::set('email', $getUserSettingData['email']);
        Context::set('uid', $getUserSettingData['uid']);
        unset($getUserSettingData);
    }

    /**
     * 会员级别权限验证
     * @param $u_id
     * @param string $path
     */
    public function checkUserRank(string $path)
    {
        $redisCacheObj = new RedisCache();
        $uid = Context::get('uid');
        $userInfo = $redisCacheObj->getUserInfoById($uid);
        unset($uid);
        if (empty($userInfo)) {
            unset($redisCacheObj, $path);
            throw new ApiException(Status::USER_INFO_ERROR);
        }
        if ($userInfo['status'] != 1) {
            unset($redisCacheObj, $path);
            throw new ApiException(Status::USER_STATUS_ERROR);
        }
        $apiInfo = $redisCacheObj->getApiInfoByPath($path);
        unset($redisCacheObj, $path);
        if (empty($apiInfo)) {
            throw new ApiException(Status::INVALID_API);
        }
        if ($userInfo['fee_end_time'] < time()) {
            $userInfo['user_rank'] = 1;
        }
        if ($apiInfo['rank_group'] == 2 && $userInfo['user_rank'] == 1) {
            unset($apiInfo);
            throw new ApiException(Status::NO_ACCESS);
        }
        Context::set('userInfo', $userInfo);
        unset($userInfo, $apiInfo);
    }
    /**
     * 读取系统设置
     */
    public function getPlatFormSetting()
    {
        // 从缓存拿 没有就从数据库读取 初始化
        $redisCache = new RedisCache();
        $settingInfo = $redisCache->getPlatformSetting();
        unset($redisCache);
        if (!empty($settingInfo)) {
            Context::set('platSetting', $settingInfo);
            unset($settingInfo);
        } else {
            throw new ApiException(Status::NULL_SYSTEM_SETTING);
        }
    }
}
